<?php
// +----------------------------------------------------------------------
// | ThinkCMF [ WE CAN DO IT MORE SIMPLE ]
// +----------------------------------------------------------------------
// | Copyright (c) 2013-2017 http://www.thinkcmf.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: 老猫 <thinkcmf@126.com>
// +----------------------------------------------------------------------
namespace app\admin\model;

use think\Model;
use think\Cache;
use think\Db;
use app\admin\Model\AccessModel;//权限查询

class AdminMenuModel extends Model
{
    /**
     * 获取所有菜单
     * @return [type] [description]
     */
    public function getAllMenus()
    {
        $res=$this->select();
        return $res;
    }

    //验证菜单是否超出三级
    public function checkParentId($parentId)
    {
        $find = $this->where(["id" => $parentId])->getField("parent_id");
        if ($find) {
            $find2 = $this->where(["id" => $find])->getField("parent_id");
            if ($find2) {
                $find3 = $this->where(["id" => $find2])->getField("parent_id");
                if ($find3) {
                    return false;
                }
            }
        }
        return true;
    }

    //验证action是否重复添加
    public function checkAction($data)
    {
        //检查是否重复添加
        $find = $this->where($data)->find();
        if ($find) {
            return false;
        }
        return true;
    }

    //验证action是否重复添加
    public function checkActionUpdate($data)
    {
        //检查是否重复添加
        $id = $data['id'];
        unset($data['id']);
        $find = $this->field('id')->where($data)->find();
        if (isset($find['id']) && $find['id'] != $id) {
            return false;
        }
        return true;
    }


    /**
     * 按父ID查找菜单子项
     * @param int $parentId 父菜单ID
     * @param boolean $withSelf 是否包括他自己
     * @return mixed
     */
    public function adminMenu($parentId, $withSelf = false)
    {
        //父节点ID
        $parentId = (int)$parentId;
        $result   = $this->where(['parent_id' => $parentId, 'status' => 1])->order("list_order", "ASC")->select();
        if ($withSelf) {
            $result2[] = $this->where(['id' => $parentId])->find();
            $result    = array_merge($result2, $result);
        }

        //权限检查
        /*if (cmf_get_current_admin_id() == 1) {
            //如果是超级管理员 直接通过
            return $result;
        }*/


        $array = [];
        //获取当前登录用户所再角色的授权菜单 2019-3-4
        $accessModel=new AccessModel();
        $role=$accessModel->get_user_role_info(cmf_get_current_admin_id());
        $auth_access=Db::name('auth_access')->where('role_id',$role['id'])->column('rule_name');
        foreach ($result as $v) {

            //方法
            $action = $v['action'];

            //public开头的通过
            if (preg_match('/^public_/', $action)) {
                $array[] = $v;
                            
            } else {

                if (preg_match('/^ajax_([a-z]+)_/', $action, $_match)) {

                    $action = $_match[1];
                }
                $rule_name = strtolower($v['app'] . "/" . $v['controller'] . "/" . $action);
                if (cmf_auth_check(cmf_get_current_admin_id(), $rule_name)) {
                    //添加权限 检查auth_access中是否存在菜单
                    $rule_names=$v['app'] . "/" . $v['controller'] . "/" . $action;
                    if($v['id'] == 1301){
                        $array[] = $v;
                    }
                    if(in_array($rule_names,$auth_access)){

                        $array[] = $v;

                    }
                }

            }

        }


        if($parentId == 0){
            // exit();
        }

        return $array;
    }

    /**
     * 获取菜单 头部菜单导航
     * @param string $parentId 菜单id
     * @return mixed|string
     */
    public function subMenu($parentId = '', $bigMenu = false)
    {
        $array   = $this->adminMenu($parentId, 1);
        $numbers = count($array);
        if ($numbers == 1 && !$bigMenu) {
            return '';
        }
        return $array;
    }

    /**
     * 菜单树状结构集合
     */
    public function menuTree()
    {
        $data = $this->getTree(0);
        return $data;
    }

    /**
     * 取得树形结构的菜单
     * @param $myId
     * @param string $parent
     * @param int $Level
     * @return bool|null
     */
    public function getTree($myId, $parent = "", $Level = 1)
    {
        $data = $this->adminMenu($myId);
        $Level++;
        if (count($data) > 0) {
            $ret = NULL;
            foreach ($data as $a) {
                $id         = $a['id'];
                $name       = $a['app'];
                $controller = ucwords($a['controller']);
                $action     = $a['action'];
                //附带参数
                $params = "";
                if ($a['param']) {
                    $params = "?" . htmlspecialchars_decode($a['param']);
                }

                 if (strpos($name, 'plugin/') === 0) {
                    $pluginName = str_replace('plugin/', '', $name);
                    $url        = cmf_plugin_url($pluginName . "://{$controller}/{$action}{$params}");
                } else {
                    $url =url("{$name}/{$controller}/{$action}{$params}");
                }
                $name = str_replace('/', '_', $name);
                $array = [
                    "icon"   => $a['icon'],
                    "id"     => $id . $name,
                    "name"   => $a['name'],
                    "parent" => $parent,
                    "url"    => $url,
                    'lang'   => strtoupper($name . '_' . $controller . '_' . $action)
                ];

                $ret[$id . $name] = $array;
                $child            = $this->getTree($a['id'], $id, $Level);
                //由于后台管理界面只支持三层，超出的不层级的不显示
                if ($child && $Level <= 3) {
                    $ret[$id . $name]['items'] = $child;
                }

            }
            return $ret;
        }

        return false;
    }

    /**
     * 更新缓存
     * @param  $data
     * @return array
     */
    public function menuCache($data = null)
    {
        if (empty($data)) {
            $data = $this->order("list_order", "ASC")->column('');
            Cache::set('Menu', $data, 0);
        } else {
            Cache::set('Menu', $data, 0);
        }
        return $data;
    }

    /**
     * 后台有更新/编辑则删除缓存
     * @param type $data
     */
    public function _before_write(&$data)
    {
        parent::_before_write($data);
        F("Menu", NULL);
    }

    //删除操作时删除缓存
    public function _after_delete($data, $options)
    {
        parent::_after_delete($data, $options);
        $this->_before_write($data);
    }

    public function menu($parentId, $with_self = false)
    {
        //父节点ID
        $parentId = (int)$parentId;
        $result   = $this->where(['parent_id' => $parentId])->select();
        if ($with_self) {
            $result2[] = $this->where(['id' => $parentId])->find();
            $result    = array_merge($result2, $result);
        }
        return $result;
    }

    /**
     * 得到某父级菜单所有子菜单，包括自己
     * @param number $parentId
     */
    public function get_menu_tree($parentId = 0)
    {
        $menus = $this->where(["parent_id" => $parentId])->order(["list_order" => "ASC"])->select();

        if ($menus) {
            foreach ($menus as $key => $menu) {
                $children = $this->get_menu_tree($menu['id']);
                if (!empty($children)) {
                    $menus[$key]['children'] = $children;
                }
                unset($menus[$key]['id']);
                unset($menus[$key]['parent_id']);
            }
            return $menus;
        } else {
            return $menus;
        }

    }


    /**
     * 保存菜单
     * @return 菜单id
     */
    /*public function saveMenu($menu)
    {
        $res=$this->where(['app'=>$menu['app'],'controller'=>$menu['controller'],'action'=>$menu['action']])->find();
        if($res){
            return $res['id'];
        }else{
            $id=$this->insertGetId($menu);
            return $id;
        }
    }*/

    /**
     * 20190928 系统2.0
     * 主系统保存主菜单操作
     * 用于主系统模块安装的时候安装子菜单等内容 
     */
    public function mainSystemSaveMenu( $symbol , $moduleId )
    {
        $obj = new \app\common\lib\ModuleAdminMenu();
        $menu = $obj->getModuleMenuList( $symbol );
        if( empty($menu ) ){
            return -1;
        }
		$moduleVersion = $this->where('id',$moduleId)->value('module_version');

        //将菜单加入到 admin_menu 数据表
        $result = $this->saveMenu( $menu , $moduleVersion );
        if( $result['mainMenu'] == -1 ){
            return -1;
        }
        //保存到模块菜单20190927
        $access = new \app\common\lib\AccessAuthorization();
        //获取当前用户的角色信息
        $roleInfo = $access->getHighestRoleInfo( cmf_get_current_admin_id() );

        $moduleM = new ModuleMenuModel();
        $res = $moduleM->saveMenu( $roleInfo ['company_id'] , $result , $moduleId );//返回主菜单id

        //母系统最高角色模块菜单授权 加入  母系统安装的所有模块均属系统最高权限角色拥有
        
        $this->saveMainSystemAuthAccess( $menu , $roleInfo );

        return $res;
    }

    /**
     * 母系统保存最高角色菜单
     * 菜单信息
     * 角色信息
     * 公司信息
     */
    private function saveMainSystemAuthAccess( $menu , $roleInfo )
    {   
        //获取公司当前菜单版本号
        $versionId = Db::name( 'company' )->where( 'id' , $roleInfo['company_id'] )->value( 'versions_type' );
        foreach ( $menu as $key => $value ) {
            //首先查询当前菜单是否存在
            $app = $value['app'];
            $controller = $value ['controller'];
            $action = $value ['action'];

            $where = [
                'app' => $app,
                'controller' => $controller,
                'action' => $action
            ];
            //查询原始菜单信息
            $originalMenu = Db::name( 'admin_menu' )->where( $where )->find();

            $ruleName = "$app/$controller/$action";
            $find = Db::name( 'auth_access' )->where( 'rule_name' , $ruleName )->where( 'role_id' , $roleInfo['id'] )->find();
            if( empty($find) ){
                //新增授权菜单
                $insert['role_id'] = $roleInfo['id'];
                $insert['rule_name'] = $ruleName;
                $insert['company'] = $roleInfo['company_id'];
                $insert['menu_id'] = $originalMenu['id'];
                $insert['type'] = 'admin_url';
                $insert['access_versions_id'] = $versionId;
                Db::name( 'auth_access' )->insertGetId( $insert );
            }
            if(  isset( $value [ 'node' ] ) && !empty( $value[ "node" ] ) ){
                $this->saveMainSystemAuthAccess( $value[ 'node' ] , $roleInfo );
            }
        }
    }

    /**
     * 系统模块菜单保存
     * 返回主菜单id
     */
    public function saveMenu( $menu , $moduleVersion = null , $parent = -1 , $subMenu = [] )
    {
        $mainMenuId = -1;
		$parentId = $parent ;
		
        foreach ( $menu as $key => $value ) {
            //没有父级菜单id
            if( $parentId == -1 ){

				if( strtolower( $value [ 'parent' ] ) != strtolower( 'admin/Plugin/default' ) ){

					//如果第一层不是模块根菜单直接失败
					break;
				}else{
					//如果模块主菜单没有预设，直接失败
					$where = [
						'app' => $value['app'],
						'controller' => $value['controller'],
						'action' => $value['action']
					];
					$moduleMainMenu = Db::name( 'admin_menu' )->where( $where )->find();
					if( empty( $moduleMainMenu) ){
						break;
					}
				}
                $parentArr = explode( '/' , $value['parent'] );
                $countParent = count( $parentArr );

                //过滤不符合标准的数据
                if( $countParent == 3 ){

                    $appParent = $parentArr[0];
                    $controllerParent = $parentArr[1];
                    $actionParent = $parentArr[2];

                }else if( $countParent == 4 ){

                    $appParent = $parentArr[0].'/'.$parentArr[1];
                    $controllerParent = $parentArr[2];
                    $actionParent = $parentArr[3];

                }else{
                    continue;
                }

                //查询父级菜单
                $where = [
                    'app' => $appParent,
                    'controller' => $controllerParent,
                    'action' => $actionParent
                ];
                $parentMenu = Db::name( 'admin_menu' )->where( $where )->find();
                if( empty( $parentMenu ) ){
                    //如果主菜单没有找到父级菜单数据就跳出循环不继续执行，菜单添加失败
                    break;
                }
                $parentId  =  $parentMenu ['id'];
            }
            //$parent > -1 说明是还要继续添加菜单 继续往下执行
            
            //首先查询当前菜单是否存在
            $app = $value['app'];
            $controller = $value ['controller'];
            $action = $value ['action'];

            $where = [
                'app' => $app,
                'controller' => $controller,
                'action' => $action
            ];

            //查询当前菜单信息 
            $currentMenuId = Db::name('admin_menu')->where( $where )->value( 'id' );

            if( empty( $currentMenuId ) ){
                //菜单不存在 ，添加新菜单
                $newMenu = $value;
                unset( $newMenu ['parent'] );
                if( isset( $newMenu ['node'] ) ) unset( $newMenu ['node'] );
                $newMenu ['parent_id'] = $parentId;
                //新菜单添加菜单版本
                if( !empty( $moduleVersion ) ){
                    $newMenu [ 'module_version' ] = "*$moduleVersion*";
                }
				$newMenu [ 'status' ] = ( $newMenu [ 'status' ] == 1 ) ? $newMenu [ 'status' ] : 0;
                $currentMenuId = Db::name( 'admin_menu' )->insertGetId( $newMenu );
				//添加验证规则
				$rule = [
					'app'	=>  $value['app'],
					'type'	=>	'admin_url',
					'name'	=>	$value['app'].'/'.$value['controller'].'/'.$value['action'],
					'status'=>	1,
					'param'	=>	$value['param'],
					'title'	=>	$value['name']
				];
				$ruleWhere = [ 'name' => $rule [ 'name' ] ];
				$find = Db::name( 'auth_rule' )->where( $ruleWhere )->find();
				if( empty ( $find )  ){
					Db::name( 'auth_rule' )->insertGetId( $rule );
				}
            }else if( !empty( $moduleVersion ) ){
                //$moduleVersion == null 表示更新传来的菜单 不需要更新模块菜单版本信息
                //当前菜单存在  ,更新菜单版本
                $this->updateModuleVersion( $currentMenuId , $moduleVersion );
            }           

            if( $parent == -1 ){

                $mainMenuId = $currentMenuId ;

            }else{
                //子菜单
                $subMenu [] = $currentMenuId;
            }

            if( isset( $value['node'] )  &&  !empty( $value['node'] ) ){
                //添加子菜单
                $subMenu = $this->saveMenu( $value['node'] , $moduleVersion , $currentMenuId , $subMenu );
            }

        }
        if( $parent > 0 ){
            return $subMenu;
        }
        return ['mainMenu' => $mainMenuId ,'subMenu' => $subMenu ] ;
    }




    /**
     * 删除
     * @param  [type] $menuId [description]
     * @return [type]         [description]
     */
    public function deleteMenu($menuId)
    {
        //return $this->where('id',$menuId)->delete();
    }

    /**
     * 更新模块菜单版本信息
     */
    private function updateModuleVersion( $menuId , $moduleVersion )
    {
        $moduleVersion = "*$moduleVersion*";
        $version  = $this->where( 'id' , $menuId )->value('module_version');

		$pos = strpos( $version , $moduleVersion );
		//如果版本不存在则追加
		if( false === $pos ){
            $moduleVersion = $version.",$moduleVersion";
        }
		$this->where( 'id' , $menuId )->update( [ 'module_version' => $moduleVersion ] );
    }
}
